package com.qire.manhua.dialog;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.CycleInterpolator;

import com.qire.antsbinder.dal.exception.DataAccessException;
import com.qire.antsbinder.dal.exception.ExceptionObservable;
import com.qire.antsrouter.AntsRouter;
import com.qire.common.basic.ObjectUtil;
import com.qire.common.basic.StringUtil;
import com.qire.common.collect.ArrayUtil;
import com.qire.common.constant.CustomEvent;
import com.qire.common.constant.Navigation;
import com.qire.common.constant.Url;
import com.qire.common.function.Action;
import com.qire.common.support.base.BaseDialog;
import com.qire.common.utils.NoticeEventBus;
import com.qire.common.utils.NoticeEventBus.NoticeEvent;
import com.qire.common.utils.NoticeEventBus.EventSubscriber;
import com.qire.common.utils.ThemeUtil;
import com.qire.common.utils.ToastHelper;
import com.qire.common.widget.snackbar.Prompt;
import com.qire.manhua.BR;
import com.qire.manhua.R;
import com.qire.manhua.dal.service.TeensModeService;
import com.qire.manhua.databinding.DialogTeensPasswordAuthorizeBinding;
import com.qire.manhua.model.enumeration.TeensModeScene;

import androidx.annotation.NonNull;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;

/**
 * 青少年密码授权弹窗:在购买金币或购买会员等页面支付前如果开启青少年模式时显示弹出。
 */
public class TeensPasswordAuthorizeDialog extends BaseDialog {

    public final PasswordCodeViewModel viewModel = new PasswordCodeViewModel();

    private final DialogTeensPasswordAuthorizeBinding viewDataBinder;

    private final TeensModeScene scene;

    private final Action onAuthorize;

    public TeensPasswordAuthorizeDialog(@NonNull Context context, TeensModeScene scene, Action onAuthorize) {
        super(context, R.style.CustomDialog_Translucent);
        this.scene = scene;
        this.onAuthorize = onAuthorize;

        viewDataBinder = DialogTeensPasswordAuthorizeBinding.inflate(LayoutInflater.from(context));
        viewDataBinder.setTeensPasswordAuthorizeDialog(this);

        setContentView(viewDataBinder.getRoot());
        setCancelable(false);
        ThemeUtil.setWindowFull(getWindow());

        // 注册API相关监听,先注销在注册防止重复注册
        unregisterObserver();
        registerObserver();
    }

    @Override
    public void dismiss() {
        super.dismiss();
        // 注销API相关监听
        unregisterObserver();
    }

    private void registerObserver() {
        NoticeEventBus.NOTICE.subscribeEvent(CustomEvent.TEENS_MODE_VERIFY, verifyEventSubscriber);
        ExceptionObservable.register(Url.TeensModeVerifyPassword, this::verifyPasswordExceptionHandle);
    }

    private void unregisterObserver() {
        NoticeEventBus.NOTICE.unSubscribeEvent(verifyEventSubscriber);
        ExceptionObservable.unregister(Url.TeensModeVerifyPassword);
    }

    /** 为了单独引用对象没，在退出时删除注册事件不至于删除别的监听事件 */
    private EventSubscriber<Boolean> verifyEventSubscriber = this::onVerifyCallback;
    /**
     * 响应总线通知：来自{@link com.qire.manhua.dal.service.TeensModeService#verifyPassword  TeensModeService}
     * @param event 携带的数据如果为 true 则表示是开启接口的返回，如果为 false 则表示是禁用接口的返回。
     * @return boolean 事件是否需要继续传递给其他订阅者处理。true 不需要已处理了 false 需要
     */
    private boolean onVerifyCallback(NoticeEvent<Boolean> event) {
        dismiss();
        if(ObjectUtil.nonNull(onAuthorize)) {
            onAuthorize.call();
        }
        return true;
    }

    private void verifyPasswordExceptionHandle(DataAccessException e) {
        ToastHelper.showSnackBarOnDialog(getWindow(), e.extraMsg, Prompt.ERROR);
        viewModel.clearPasswordCode();
        animateError();
    }

    private void animateError() {
        viewDataBinder.passwordCode.animate().setInterpolator(new CycleInterpolator(2)).translationX(20f).start();
    }

    public void dismissOnClick(View view) {
        dismiss();
    }

    public void forgetPasswordBtnOnClick(View view) {
        dismiss();
        AntsRouter.ROUTER.buildCard(Navigation.Page.TeensRetrievePasswordPage).navigation();
    }


    public final class PasswordCodeViewModel extends BaseObservable {

        private final String[] passwordCodes = new String[4];
        private int codeFocusIndex = 0;

        private PasswordCodeViewModel() { }

        public void clearPasswordCode() {
            ArrayUtil.fill(passwordCodes, "");
            codeFocusIndex = 0;
            notifyPropertyChanged(BR.passwordCode);
            notifyPropertyChanged(BR.codeFocusIndex);
        }

        public boolean isFull() {
            for(String code : passwordCodes) {
                if(StringUtil.isEmpty(code)) {
                    return false;
                }
            }
            return true;
        }

        public String toPasswordCode() {
            StringBuilder passwordCodeBuilder = new StringBuilder(4);
            for(String code : passwordCodes) {
                if(StringUtil.notEmpty(code)) {
                    passwordCodeBuilder.append(code.charAt(0));
                }
            }
            return passwordCodeBuilder.toString();
        }

        public void setPasswordCode(CharSequence[] passwordCode) {
            ArrayUtil.replace(passwordCode, this.passwordCodes);
            if(isFull()) {
                new TeensModeService().verifyPassword(toPasswordCode(), scene.sceneLabel);
            }
        }

        @Bindable
        public CharSequence[] getPasswordCode() {
            return ArrayUtil.copy(passwordCodes);
        }

        @Bindable
        public int getCodeFocusIndex() {
            return codeFocusIndex;
        }
    }
}
